/*
* vga.c - Mokri
* Contributors: xMine
* (Any new Contributor may add himself/herself to the list)
* Changes and fixes to be made: Any Task is in Ring0 => Kernel rights
*/

#include "vga.h"
#include "scheduler.h"

extern volatile char *videoram;
static uint16_t vga_base = 0x0; // Ist höchstwahrscheinlich 0x03D0. Wir lesen den genauen Wert in der vga_init aus

/* Initialisiert VGA
 * Parameter: Keine
 * Rückgaben: Keine
 */
void vga_init () {
	vga_base = *((uint16_t*)(0x400+0x63));
	// Leert alle 8 Pages (4000*8 Bytes)
	memset ((void*)videoram, 0x0, 4000*8);
}

/* Setzt die Position des Hardware Cursors.
 * Parameter: Position X, Position Y
 * Rückgaben: Keine
 */
void vga_move_cursor (uint8_t pos_x, uint8_t pos_y) {
	if (!vga_base) {
		return;
	}
	
	uint16_t pos = (pos_y * SCREEN_WIDTH) + pos_x;
	
	outb(vga_base  , 15);
	outb(vga_base+1, pos & 0xFF); // Niederes Byte übertragen
	outb(vga_base  , 14);
	outb(vga_base+1, (pos >> 8) & 0xFF); // Höheres Byte übertragen
}

/* Versteckt den Hardware Cursor
 * Parameter: Keine
 * Rückgaben: Keine
 */
void vga_hide_cursor () {
	vga_move_cursor (0, 26);
}

/* Setzt die zu benutzende Hardware Seite
 * Parameter: Seite (0-7)
 * Rückgaben: Keine
 */
void vga_set_page (uint32_t page) {
	if (page > 7) {
		return;
	}
	
	videoram = (char*)(page * ((SCREEN_WIDTH * SCREEN_HEIGHT + 0xff) & 0xff00));
	uint32_t vr = (page * ((SCREEN_WIDTH * SCREEN_HEIGHT + 0xff) & 0xff00)); 
	
	outb(vga_base  , 13);
	outb(vga_base+1, vr & 0xff); // Low Byte schreiben
	outb(vga_base  , 12);
	outb(vga_base+1, (vr >> 8) & 0xff); // High Byte schreiben
}